package cn.vehicle.domains.vo.req.zs;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;

import java.util.List;

@Data
public class AlarmInfoPlateReq {

    /**
     * 默认通道号（预留）
     */
    private Integer channel;
    /**
     * 设备名称
     */
    private String deviceName;
    /**
     * 设备 ip 地址
     */
    @JsonProperty("ipaddr")
    private String ipAddr;
    /**
     * 实际数据
     */
    private DetectedResult result;
    /**
     * 规则 ID
     */
    @JsonProperty("rule_id")
    private Integer ruleId;
    /**
     * 设备序列号，设备唯一
     */
    @JsonProperty("serialno")
    private String serialNo;
    /**
     * 用户自定义数据
     */
    @JsonProperty("user_data")
    private String userData;
    /**
     * OEM 标识，需要在 Tcp 协议中设置了客户定制 sn 才会生效，否则不会发送此字段到服务器。
     */
    @JsonProperty("oemserialno")
    private String oemSerialNo;


    @Data
    public static class DetectedResult {
        /**
         * 车牌识别结果信息
         */
        @JsonProperty("PlateResult")
        private PlateResult PlateResult;
    }

    /**
     * 车牌识别结果信息
     */
    @Data
    public static class PlateResult {
        /**
         * 车牌真实宽度
         */
        @JsonProperty("plate_true_width")
        private Integer plateTrueWidth;
        /**
         * 车牌距离
         */
        @JsonProperty("plate_distance")
        private Integer plateDistance;
        /**
         * 是否伪车牌，0：真实车牌，1：伪车牌
         */
        @JsonProperty("is_fake_plate")
        private Integer isFakePlate;
        /**
         * 车头位置信息
         */
        @JsonProperty("car_location")
        private CarLocation carLocation;

        /**
         * 亮度评价（预留）
         */
        private Integer bright;
        /**
         * 车身亮度（预留）
         */
        private Integer carBright;
        /**
         * 车身颜色（预留）参见表{@link ZSVehicleColor}
         */
        private Integer carColor;
        public ZSVehicleColor getCarColorEnum() {
            return ZSVehicleColor.codeOf(carColor);
        }
        /**
         * 车辆品牌信息
         */
        @JsonProperty("car_brand")
        private CarBrand carBrand;

        /**
         * R5 未使用
         */
        @JsonProperty("clean_time")
        private Integer cleanTime;
        /**
         * 车牌颜色，参见{@link ZSLicensePlateColor}
         */
        private Integer colorType;

        public ZSLicensePlateColor getColorTypeEnum() {
            return ZSLicensePlateColor.codeOf(colorType);
        }

        /**
         * 车牌颜色
         */
        private Integer colorValue;
        /**
         * 识别结果可信度 1-100
         */
        private Integer confidence;
        /**
         * 车的行进方向。取值参见{@link ZSMovementDirection}
         */
        private Integer direction;
        public ZSMovementDirection getDirectionEnum() {
            return ZSMovementDirection.codeOf(direction);
        }
        /**
         * 车辆特征码
         */
        @JsonProperty("feature_code")
        private String featureCode;

        /**
         * 识别大图片内容经过base64后的字符串，需要开启发送大图片
         */
        private String imageFile;
        /**
         * 识别大图片内容长度，注意不是 base64 后的长度，需要开启发送大图片
         */
        private Integer imageFileLen;
        /**
         * 识别车牌小图片内容经过base64 后的字符串，需要开启发送小图片
         */
        private String imageFragmentFile;
        /**
         * 识别车牌小图片内容长度，注意不是 base64 后的长度，需要开启发送小图片
         */
        private Integer imageFragmentFileLen;
        /**
         * gioouts。开闸输出信息（新增）
         */
        private List<Gioout> gioouts;
        /**
         * 设备离线状态，0：在线，1：离线
         */
        @JsonProperty("isoffline")
        private Integer isOffline;
        /**
         * 车牌号字符串，如 “京AAAAAA”.(看起来是unicode编码)
         */
        private String license;
        /**
         * 新式小型车牌扩展,仅在车牌小型车牌的时候有效
         */
        @JsonProperty("license_ext_type")
        private Integer licenseExtType;
        /**
         * 车牌在图片中位置
         */
        private Location location;

        /**
         * 识别结果车牌ID
         */
        @JsonProperty("plateid")
        private Integer plateId;
        /**
         * 车牌列表
         */
        private List<Plate> plates;
        /**
         * 识别结果对应帧的时间戳
         */
        private TimeStamp timeStamp;
        /**
         * 识别所用时间
         */
        private Integer timeUsed;
        /**
         * 当前结果的触发类型，参见{@link ZSTriggerYType}
         */
        private Integer triggerType;
        public ZSTriggerYType getTriggerTypeEnum() {
            return ZSTriggerYType.codeOf(triggerType);
        }
        /**
         * 车牌类型。取值范围参见表{@link ZSLicensePlateType}
         */
        private Integer type;
        public ZSLicensePlateType getTypeEnum() {
            return ZSLicensePlateType.codeOf(type);
        }
    }

    @Data
    public static class CarBrand {
        /**
         * 车辆品牌
         */
        private Integer brand;
        /**
         * 车辆类型。参见{@link ZSVehicleType}
         */
        private Integer type;

        public ZSVehicleType getTypeEnum() {
            return ZSVehicleType.codeOf(type);
        }

        /**
         * 车系编码
         */
        private Integer year;
    }

    @Data
    public static class CarLocation {
        @JsonProperty("RECT")
        private Rect RECT;
    }

    @Data
    public static class Rect {
        private Integer bottom;
        private Integer left;
        private Integer right;
        private Integer top;

        public RectangleBo toRectangle() {
            final Integer left = this.getLeft();
            final Integer top = this.getTop();
            final Integer right = this.getRight();
            final Integer bottom = this.getBottom();
            return new RectangleBo(left, top, right - left, bottom - top);
        }
    }


    @Data
    @AllArgsConstructor
    public static class RectangleBo {

        public int x;

        public int y;

        public int width;

        public int height;
    }

    @Data
    public static class Gioout {
        /**
         * 开闸类型，参见{@link ZSGateOpenType}
         */
        @JsonProperty("ctrltype")
        private Integer ctrlType;

        public ZSGateOpenType getCtrlTypeEnum() {
            return ZSGateOpenType.codeOf(ctrlType);
        }

        /**
         * IO OUT序号，当前最大4个IOout
         */
        @JsonProperty("ionum")
        private String ioNum;
    }

    @Data
    public static class Location {
        @JsonProperty("RECT")
        private Rect RECT;
    }

    @Data
    public static class Plate {
        /**
         * 车牌颜色，参见{@link ZSLicensePlateColor}
         */
        private Integer color;

        public ZSLicensePlateColor getColorEnum() {
            return ZSLicensePlateColor.codeOf(color);
        }

        private String imageFragmentFile;
        private Integer imageFragmentFileLen;
        /**
         * 加密采用gbk编码，不加密采用 utf8 编码。
         */
        private String license;
        /**
         * 车牌宽度
         */
        private Integer plateWidth;
        /**
         * 车牌坐标
         */
        private Pos pos;
        /**
         * 车辆类型。取值参见表 {@link ZSVehicleType}。
         */
        private Integer type;

        public ZSVehicleType getTypeEnum() {
            return ZSVehicleType.codeOf(type);
        }
    }

    @Data
    public static class Pos {
        private Integer bottom;
        private Integer left;
        private Integer right;
        private Integer top;
    }

    @Data
    public static class TimeStamp {
        /**
         * 时间戳结构体类型
         */
        @JsonProperty("Timeval")
        private Timeval Timeval;
    }

    @Data
    public static class Timeval {
        @JsonProperty("decday")
        private Integer day;
        @JsonProperty("dechour")
        private Integer hour;
        @JsonProperty("decmin")
        private Integer minute;
        @JsonProperty("decmon")
        private Integer month;
        @JsonProperty("decsec")
        private Integer seccond;
        @JsonProperty("decyear")
        private Integer year;
        /**
         * 从1970年1月1日到对应帧的秒
         */
        @JsonProperty("sec")
        private Long timestampSeconds;
        /**
         * 从1970年1月1日到对应帧的毫秒
         */
        @JsonProperty("usec")
        private Long timestamp;
    }

    /**
     * 表 3 触发类型定义表
     */
    @Getter
    @AllArgsConstructor
    public enum ZSTriggerYType {
        UNDEFINED(Integer.MIN_VALUE, "找不到的类型"),
        AUTO(0, "自动触发"),
        IO(1, "外部输入触发（IO 输入）"),
        SDK(4, "软件触发（SDK）"),
        VIRTUAL_COIL(8, "虚拟线圈触发"),
        CAR_STAY(64, "车滞留事件"),
        CAR_STAY_RECOVER(65, "车滞留恢复事件"),
        CAR_BACK(66, "车折返事件"),
        ;
        private final int code;
        private final String desc;

        public static ZSTriggerYType codeOf(Integer code) {
            if (code == null) {
                return null;
            }
            for (ZSTriggerYType triggerYType : values()) {
                if (triggerYType.code == code) {
                    return triggerYType;
                }
            }
            return null;
        }
    }

    /**
     * 表 4 车牌类型定义表
     */
    @Getter
    @AllArgsConstructor
    public enum ZSLicensePlateType {
        UNDEFINED(Integer.MIN_VALUE, "找不到的类型"),
        UNKNOWN(0, "未知车牌"),
        BLUE_SMALL_CAR(1, "蓝牌小汽车"),
        BLACK_SMALL_CAR(2, "黑牌小汽车"),
        SINGLE_YELLOW(3, "单排黄牌"),
        DOUBLE_YELLOW(4, "双排黄牌"),
        POLICE(5, "警车车牌"),
        ARMED_POLICE(6, "武警车牌"),
        PERSONALIZED(7, "个性化车牌"),
        SINGLE_ARMY(8, "单排军车牌"),
        DOUBLE_ARMY(9, "双排军车牌"),
        EMBASSY(10, "使馆车牌"),
        HK_TO_MAINLAND(11, "香港进出中国大陆车牌"),
        AGRICULTURAL(12, "农用车牌"),
        TRAINING(13, "教练车牌"),
        MACAO_TO_MAINLAND(14, "澳门进出中国大陆车牌"),
        DOUBLE_LAYERED_ARMED_POLICE(15, "双层武警车牌"),
        ARMED_POLICE_UNIT(16, "武警总队车牌"),
        DOUBLE_LAYERED_ARMED_POLICE_UNIT(17, "双层武警总队车牌"),
        CIVIL_AVIATION(18, "民航车牌"),
        NEW_ENERGY(19, "新能源车牌"),
        LARGE_NEW_ENERGY(20, "大型新能源"),
        EMERGENCY(21, "应急车"),
        LEADER(22, "领导车"),
        NEW_STANDARD_FUEL(23, "新标准燃油车"),
        NEW_STANDARD_NEW_ENERGY(24, "新标准新能源"),
        AIRPORT(25, "机场车"),
        FOREIGN(26, "海外车牌（所有海外车牌类型）"),
        TEMPORARY(29, "假车牌"),
        BADGE(30, "车标"),
        UNLICENSED(31, "无牌车"),
        ;
        private final int code;
        private final String desc;

        public static ZSLicensePlateType codeOf(Integer code) {
            if (code == null) {
                return null;
            }
            for (ZSLicensePlateType type : values()) {
                if (type.code == code) {
                    return type;
                }
            }
            return null;
        }
    }

    /**
     * 表 5 车牌颜色定义表
     */
    @Getter
    @AllArgsConstructor
    public enum ZSLicensePlateColor {
        UNDEFINED(Integer.MIN_VALUE, "找不到的类型"),
        UNKNOWN(0, "未知"),
        BLUE(1, "蓝色"),
        YELLOW(2, "黄色"),
        WHITE(3, "白色"),
        BLACK(4, "黑色"),
        GREEN(5, "绿色"),
        YELLOW_GREEN(6, "黄绿色"),
        ;
        private final int code;
        private final String desc;

        public static ZSLicensePlateColor codeOf(Integer code) {
            if (code == null) {
                return null;
            }
            for (ZSLicensePlateColor color : values()) {
                if (color.code == code) {
                    return color;
                }
            }
            return null;
        }


    }


    /**
     * 表 6 车身颜色定义表
     */
    @Getter
    @AllArgsConstructor
    public enum ZSVehicleColor {
        UNDEFINED(Integer.MIN_VALUE, "找不到的类型"),
        WHITE(0, "白"),
        SILVER(1, "银（灰）"),
        YELLOW(2, "黄"),
        PINK(3, "粉"),
        RED(4, "红"),
        GREEN(5, "绿"),
        BLUE(6, "蓝"),
        BROWN(7, "棕"),
        BLACK(8, "黑"),
        UNKNOWN(255, "未知"),
        ;
        private final int code;
        private final String desc;

        public static ZSVehicleColor codeOf(Integer code) {
            if (code == null) {
                return null;
            }
            for (ZSVehicleColor color : values()) {
                if (color.code == code) {
                    return color;
                }
            }
            return null;
        }


    }

    /**
     * 表 7 运动方向定义表
     */
    @Getter
    @AllArgsConstructor
    public enum ZSMovementDirection {
        UNDEFINED(Integer.MIN_VALUE, "找不到的类型"),
        UNKNOWN(0, "未知"),
        LEFT(1, "左"),
        RIGHT(2, "右"),
        UP(3, "上"),
        DOWN(4, "下"),
        ;
        private final int code;
        private final String desc;

        public static ZSMovementDirection codeOf(Integer code) {
            if (code == null) {
                return null;
            }
            for (ZSMovementDirection direction : values()) {
                if (direction.code == code) {
                    return direction;
                }
            }
            return null;
        }
    }


    /**
     * 表 8 车辆类型定义表
     */
    @Getter
    @AllArgsConstructor
    public enum ZSVehicleType {
        UNDEFINED(Integer.MIN_VALUE, "找不到的类型"),
        UNKNOWN(0x00, "未知"),
        SEDAN(0x01, "轿车"),
        SUV(0x02, "SUV"),
        MPV(0x03, "MPV"),
        SMALL_BUS(0x04, "小型客车"),
        LARGE_BUS(0x05, "大型客车"),
        SMALL_TRUCK(0x06, "小型货车"),
        LARGE_TRUCK(0x07, "大型货车"),
        ;
        private final int code;
        private final String desc;

        public static ZSVehicleType codeOf(Integer code) {
            if (code == null) {
                return null;
            }
            for (ZSVehicleType type : values()) {
                if (type.code == code) {
                    return type;
                }
            }
            return null;
        }
    }


    /**
     * 表 9 开闸类型定义表
     */
    @Getter
    @AllArgsConstructor
    public enum ZSGateOpenType {
        UNDEFINED(Integer.MIN_VALUE, "找不到的类型"),
        NO_OPEN(0, "无开闸"),
        SERVER_TRIGGER(1, "服务器触发开闸"),
        WHITE_LIST(2, "脱机状态白名单开闸"),
        ;
        private final int code;
        private final String desc;

        public static ZSGateOpenType codeOf(Integer code) {
            if (code == null) {
                return null;
            }
            for (ZSGateOpenType type : values()) {
                if (type.code == code) {
                    return type;
                }
            }
            return null;
        }
    }

}
